#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import time
import threading
from s2c.engine.file_scanner import FileScanner
from s2c.engine.process_scanner import ProcessScanner
from s2c.tools.dict import scan_service_app
from s2c.tools.cmd_executed import cmd_exec
from s2c.tools.docker import get_docker_image_list
from s2c.tools.http import http_status_success, http_status_fail, http_res
from s2c.tools.utils import check_obj_key, read_file, get_system_date_time, run_cmd, write_file, \
    check_arr_key, get_path_parent
from bottle import route, run, template, get, post, request, response, static_file
from s2c.rules.conf import DOCKER_PATH_TMP, TARGET_SYSTEM_OPTION, SYS_CURRENT
from s2c.engine.db_helper import DbHelper

from s2c.tools.function import download_file_write_db, get_docker_file, check_dict_status

g_http_staic_path = os.path.dirname(os.path.abspath(__file__))


# print('当前路径:', g_http_staic_path)


class RunExec(threading.Thread):
    def __init__(self, cmd):
        self.cmd = cmd
        super().__init__()

    def run(self) -> None:
        print('-------cmd----', self.cmd)
        cmd_exec(self.cmd)


@route('/hello/<name>')
def index(name):
    return template('<b>Hello {{name}}</b>!', name=name)


@get('/login')  # or @route('/login', method='POST')
def login():
    # return json.dumps([1,2,3])
    print('---------', response)
    return http_res(http_status_success, 'ok')


# 获取目标系统版本选项
@get('/system/targetsystem')
def targetsystem():
    print('/system/targetsystem')

    ret_obj = {
        'option': TARGET_SYSTEM_OPTION,
        'local_target': ''
    }
    # 如果存在，返回当前已经设置好的目标系统
    if os.path.exists('targetver'):
        ret_obj['local_target'] = read_file('targetver')
    return http_res(http_status_success, ret_obj)


# 设置目标系统版本
@post('/system/settargetsystem')
def settargetsystem():
    print('/system/settargetsystem', request.json)
    data = request.json
    if (data['data']):
        write_file('targetver', data['data'])
        return http_res(http_status_success)
    return http_res(http_status_fail)


@get('/system/dictstatus')
def get_dictstatus():
    print('/system/dictstatus')

    # 如果目标文件不存在，直接返回
    if os.path.exists('targetver') == False:
        return http_res(http_status_success, 0)
    # TRUE表示文件已经存在
    if check_dict_status():
        return http_res(http_status_success, 1)
    return http_res(http_status_success, 0)


# 获取后台系统时间
@get('/system/time')
def get_time():
    print('/system/time')
    # 返回后端系统时间
    # return int(time.time())
    # ret_time = int(time.time())
    ret_time = get_system_date_time()
    print('--time----', ret_time)
    return http_res(http_status_success, ret_time)


# 请求扫描当前系统文件
@get('/system/file')
def scan_file():
    print('/system/file')
    # 扫描之前先删除临时文件
    if os.path.exists('dbtmp'):
        os.remove('dbtmp')
    # 默认扫描根目录
    fs = FileScanner('/', dict_type=SYS_CURRENT)
    fs.scan()
    fs.start_task_pool()
    # 启动扫描程序
    return http_res(http_status_success)


# 请求扫描当前系统文件
@get('/system/scanstatus')
def scan_file_status():
    print('/system/file')
    index = read_file('dbtmp')
    if index == False:
        return http_res(http_status_fail, 'dbtmp文件不存在')
    print('---------', index)
    g_db = DbHelper()
    ret = g_db.get_db_scan_file_status(int(index))
    g_db.close()
    return http_res(http_status_success, ret)


# 请求扫描系统进程信息
@get('/system/process')
def system_process():
    print('/system/process')
    # 返回进程服务信息
    scanner = ProcessScanner()
    scanner.scan()
    print('--------process-----', scanner.ps_list)

    ret_new = []
    tmp_arr = []
    ret_all = []
    tmp_ret_all = []
    for item in scanner.ps_list:
        if item['name'].lower() in scan_service_app and (item['name'].lower() in tmp_arr) == False:
            ret_new.append({'name': item['name']})
            tmp_arr.append(item['name'])
        elif item['user'].lower() in scan_service_app and (item['user'].lower() in tmp_arr) == False:
            ret_new.append({'name': item['user']})
            tmp_arr.append(item['user'])

    for item in scanner.ps_list:
        if check_arr_key(tmp_ret_all, item['name']) == False:
            tmp_ret_all.append(item['name'])
            ret_all.append({'name': item['name'], 'user': item['user']})

    ret_obj = {
        'utils': ret_new,
        'all': ret_all
    }

    # 如果是数组需要所以dumps转换一下
    return http_res(http_status_success, ret_obj)


# 根据进程名称，获取进程相关文件信息
@post('/system/name')
def system_name():
    print('/system/name', request.json)
    data = request.json
    return http_res(http_status_success, get_docker_file(data['name']))


# 更新dockerfile文件
@post('/system/updatedockerfile')
def system_name():
    print('/system/updatedockerfile', request.json)
    data = request.json
    if (data['data']):
        write_file('Dockerfile', data['data'])
        return http_res(http_status_success)
    return http_res(http_status_fail)


@get('/system/dockerfile')
def get_docker():
    print('/system/dockerfile')
    # 返回当前目录下的docker file文件
    ret = read_file('Dockerfile')
    if ret == False:
        return http_res(http_status_fail)
    return http_res(http_status_success, ret)


@get('/system/buildimage')
def buildimage():
    print('/system/buildimage')
    name = read_file('dockertmp')
    if name == False:
        return http_res(http_status_fail, 'docker对应的文件不存在，请重新扫描服务')

        # build images之前先清理当前目录下的images文件夹，避免image文件变大
    if os.path.exists('images'):
        os.system('rm -rf ./images')
    # 执行docker build 的前先检查文件是否正确
    cmd = 'docker build -t autobuild' + name + ':00 .'
    print('-----/system/buildimage-------', cmd)
    # cmd = 'ping baidu.com'
    run = RunExec(cmd)
    run.start()
    # cmd_exec("ping baidu.com")
    """ status, ret = run_cmdb(cmd)
    print('------build--ret-----', ret)
    if status:
        return http_res(http_status_success, ret) """
    return http_res(http_status_success, cmd)


# 执行docker run
@post('/system/dockerrun')
def docker_run():
    print('/system/dockerrun', request.json)
    data = request.json
    print('------------------------')
    print('------build--cmd-----', data['cmd'])
    if check_obj_key(data, 'cmd') == False:
        return http_res(http_status_fail, 'cmd keyword is not exist')
    # status, ret = run_cmd(data['cmd'])
    cmd_exec(data['cmd'])
    time.sleep(2)
    g_db = DbHelper()
    ret = g_db.get_db_cmd_runing_status(0, data['cmd'])
    g_db.close()
    out_str = ''
    for line in ret:
        if line['status'] == 1:
            out_str += line['str']
    print('------build--ret-----', out_str)
    return http_res(http_status_success, out_str)


# 添加需要手动迁移的文件路径
@post('/system/adddockerpath')
def docker_run():
    print('/system/adddockerpath', request.json)
    data = request.json
    print('-----------adddockerpath-------------', data)
    if os.path.isdir(data['path']) or os.path.isfile(data['path']):
        # 复制手动添加的文件夹路径
        cmd = '\cp -rf ' + data['path'] + ' ' + DOCKER_PATH_TMP + get_path_parent(data['path'])
        print('-----------adddockerpath--------cmd-----', cmd)
        os.system(cmd)
        return http_res(http_status_success, data['path'])
    else:
        return http_res(http_status_fail, 'file path is not exist')


# 请求当前cmd执行状态
@post('/system/cmdtatus')
def buil_status():
    print('/system/cmdtatus', request.json)
    data = request.json
    if check_obj_key(data, 'data') == False:
        return http_res(http_status_fail, 'data keyword is not exist')
    if check_obj_key(data['data'], 'index') == False:
        return http_res(http_status_fail, 'index keyword is not exist')
    if check_obj_key(data['data'], 'cmd') == False:
        return http_res(http_status_fail, 'cmd keyword is not exist')
    index = data['data']['index']
    print('---------', index)
    g_db = DbHelper()
    ret = g_db.get_db_cmd_runing_status(int(index), data['data']['cmd'])
    g_db.close()
    return http_res(http_status_success, ret)


@get('/system/scanimage')
def scanimage():
    print('/system/scanimage')
    status, ret = run_cmd('docker images')
    print('------build--ret-----', ret)
    if status == False:
        return http_res(http_status_fail, ret)
    ret_arr = get_docker_image_list(ret)
    return http_res(http_status_success, ret_arr)


@post('/system/downloadimage')
def downloadimage():
    print('/system/downloadimage', request.json)
    data = request.json
    if data['data']:
        data = data['data']
    else:
        return http_res(http_status_fail)
    if os.path.exists('images') == False:
        print('创建路径')
        os.mkdir('images')
    file_name = data['name'] + '_' + data['tag'] + '_' + data['imageid'] + '.tar'

    cmd = 'docker save -o images/' + file_name + ' ' + data['imageid']
    print('------cmd--------', cmd)
    status, ret = run_cmd(cmd)
    if status == False:
        return http_res(http_status_fail, ret)
    if os.path.exists('images/' + file_name):
        return http_res(http_status_success, 'app/dockerimage/' + file_name)
    return http_res(http_status_fail, ret)


@post('/system/downloadservicefile')
def downloadservicefile():
    print('/system/downloadservicefile', request.json)
    data = request.json
    app_name = ''
    if data['data']:
        app_name = data['data']
    else:
        return http_res(http_status_fail)
    if os.path.exists(DOCKER_PATH_TMP) == False:
        return http_res(http_status_fail, '服务文件不存在, 请重新扫描')

    file_name = app_name + '.tar.gz'

    cmd = 'tar -zcvf ' + file_name + ' lib Dockerfile'
    print('------cmd--------', cmd)
    status, ret = run_cmd(cmd)
    print('---run_cmd-------', ret)
    if os.path.exists(file_name) == False:
        return http_res(http_status_fail, '压缩文件不存在')
    if status == False:
        return http_res(http_status_fail, ret)

    # 复制前先创建images临时文件夹
    os.system('mkdir -p images')
    run_cmd('\cp ' + file_name + ' images/')

    if os.path.exists('images/' + file_name):
        return http_res(http_status_success, 'app/dockerimage/' + file_name)
    return http_res(http_status_fail, ret)


@post('/system/deleteimage')
def deleteimage():
    print('/system/deleteimage', request.json)
    data = request.json
    if data['data']:
        data = data['data']
    else:
        return http_res(http_status_fail, data)
    cmd = 'docker rmi ' + data['imageid']
    print('------cmd--------', cmd)
    status, ret = run_cmd(cmd)
    if status:
        return http_res(http_status_success, ret)
    return http_res(http_status_fail, ret)


@get('/system/download')
def get_download_file():
    print('/system/download', request.json)
    # 扫描之前先删除临时文件
    if os.path.exists('dbtmp'):
        os.remove('dbtmp')
    download_file_write_db()
    return http_res(http_status_success)


@get('/system/info')
def get_system_info():
    print('/system/info', request.json)
    return "<p>Login failed.</p>"


@get('/app/<filename>')
def server_static(filename):
    # return static_file(filename, root='/path/to/your/static/files')
    return static_file(filename, root=g_http_staic_path + '/web')


@get('/app/js/<filename>')
def server_static(filename):
    return static_file(filename, root=g_http_staic_path + '/web/js')


@get('/app/css/fonts/<filename>')
def server_static(filename):
    return static_file(filename, root=g_http_staic_path + '/web/css')


@get('/app/css/<filename>')
def server_static(filename):
    return static_file(filename, root=g_http_staic_path + '/web/css')


@get('/app/icon/<filename>')
def server_static(filename):
    return static_file(filename, root=g_http_staic_path + '/web/icon')


@get('/app/image/<filename>')
def server_static(filename):
    return static_file(filename, root=g_http_staic_path + '/web/image')


@get('/app/dockerimage/<filename>')
def server_static(filename):
    return static_file(filename, root=g_http_staic_path + '/images')


# 启动http server
def http_server(port=9527):
    run(host='0.0.0.0', port=port)


if __name__ == "__main__":
    print('---http server----')
